package com.jasmine.bjstkserver.server.picture;

import cn.hutool.core.util.StrUtil;
import com.jasmine.auth.util.AuthUtil;
import com.jasmine.bjstkserver.core.config.exception.BjsException;
import com.jasmine.bjstkserver.manager.os.OsManager;
import com.jasmine.bjstkserver.mapper.PictureMapper;
import com.jasmine.bjstkserver.server.dict.DictService;
import com.jasmine.bjstkserver.server.picture.model.PictureEntity;
import com.jasmine.bjstkserver.server.picture.model.PictureReq;
import com.jasmine.bjstkserver.server.picture.model.PictureRes;
import com.jasmine.core.constants.BjsConstants;
import com.jasmine.core.util.BeanUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @author : jasmineXz
 */
@Service
public class PictureServiceImpl implements PictureService {

    @Autowired
    private PictureMapper pictureMapper;

    @Autowired
    private OsManager osManager;

    @Autowired
    private DictService dictService;


    /**
     * 查询照片列表
     * @param picture 文件信息
     * @return 照片列表
     */
    @Override
    public List<PictureRes> findList(PictureReq picture) {
        if (picture.getFolderId() == null) {
            picture.setFolderId(BjsConstants.DEFAULT_FOLDER_ID);
        }
        if(null == picture.getStart() || null == picture.getLimit() || 0 == picture.getLimit()) {
            picture.setStart(0);
            picture.setLimit(16);
        }
        return pictureMapper.findList(picture);
    }


    /**
     * 新增图片
     * ------------------------- 完善设计 -------------------------
     * 将文件名+用户ID放入布隆过滤器,判断文件名重复的效率更高
     * 单碍于布隆过滤器机制,删除,需要增加白名单机制,并提供定时重置布隆过滤器的功能
     * 重置布隆过滤器的瞬间可能会造成大量请求请求到库最好设置多个布隆过滤器,将键hash
     * 后查询对应布隆过滤器,刷新时不刷新全部而刷新某个hash区间的布隆过滤器
     *
     * ------------------------- 当前设计 -------------------------
     * 目前仍然从数据库查重
     *
     * @param picture 图片文件
     * @param uploadPath 上传路径,配置在文件夹夹中
     * @param folderId 文件夹ID
     * @return OS路径
     */
    @Override
    public String insert(MultipartFile picture, String uploadPath, Integer folderId) {

        String pictureName = picture.getOriginalFilename();

        PictureReq req = new PictureReq();
        req.setUserId(AuthUtil.getUserId());
        req.setName(pictureName);
        if(pictureMapper.checkRepeat(req) > 0) {
            throw new IllegalArgumentException("名称重复");
        }

        // 上传OS
        String url =
            osManager.put(
                picture,
                StrUtil.isNotBlank(uploadPath) ?
                    uploadPath + pictureName :
                    BjsConstants.DEFAULT_OS_PATH + pictureName
            );

        String format = StrUtil.subAfter(pictureName,".",true);

        PictureEntity insPicture = new PictureEntity();
        insPicture.setUserId(AuthUtil.getUserId());
        insPicture.setName(pictureName);                              // 文件名
        insPicture.setSourceName(pictureName);                        // 原文件名
        insPicture.setFolderId(null == folderId ? BjsConstants.DEFAULT_FOLDER_ID : folderId);   // 文件夹, 为null则为默认文件夹
        insPicture.setUrl(url);                                       // os地址
        insPicture.setFormat(format);                                 // 格式
        insPicture.setSize(picture.getSize());                        // 大小

        pictureMapper.insertSelective(insPicture);

        return url;
    }


    /**
     * 修改文件信息,名称,喜欢等
     * @param pictureReq 文件内容
     * @return 影响行数
     */
    @Override
    public Integer update(PictureReq pictureReq) throws Exception {
        return pictureMapper.updateByPrimaryKeySelective(BeanUtil.copyObject(pictureReq,PictureEntity.class));
    }


    /**
     * 重置文件夹下的文件到未分类下,即文件夹ID = [-1]
     * @param userId 用户ID
     * @param folderId 被删除文件夹ID
     */
    @Override
    public Integer resetFolder(Integer userId, Integer folderId) {
        return pictureMapper.resetFolder(userId,folderId);
    }


    /**
     * 批量修改文件的文件夹
     * @param pictureReq 文件夹
     * @return 影响行数
     */
    @Override
    public Integer changeFolder(PictureReq pictureReq) {
        return pictureMapper.changeFolder(pictureReq);
    }


    /**
     * 删除文件,将异步删除OS文件
     * @param pictureId 文件ID
     * @param url 文件路径
     * @return 影响行数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer delete(Integer pictureId,String url) {
        if (StrUtil.isBlank(url)) {
            PictureEntity picture = pictureMapper.selectByPrimaryKey(pictureId);
            Optional.ofNullable(picture).orElseThrow(() -> new BjsException("文件不存在"));
            url = picture.getUrl();
        }
        Integer num = pictureMapper.deleteByPrimaryKey(pictureId);
        osManager.deleteAsync(url,AuthUtil.getUserId());
        return num;
    }




    /* ------------------- 统计 ------------------- */




    @Override
    public Map<String, Object> statistics(PictureReq pictureReq) {
        Map<String,Object> map = pictureMapper.statistics(pictureReq);
        map.put("osType",dictService.getDictValue("1000","OSTYPE")); // 获取OS类型
        return map;
    }
}

